今天是第四天我們可以寫一個Kubernetes模仿google存取資料系統,因為google是目前大家用量最大的伺服器,因此google是怎麼去存取大量資料的我是相當好奇,因此我想寫一個k8s來模仿,以下是程式碼
要在 Kubernetes (K8s) 上模仿 Google 的資料存取系統,主要涉及設計一個分散式資料庫,類似 Google 的 Bigtable、Spanner 或是 Google 的分散式檔案系統 (GFS)。這些系統強調高可用性、分區容錯、線性擴展能力,並提供一致性和可用性保證。
Kubernetes 是一個容器管理平台,透過其提供的服務來實現一個分散式、擴展的系統架構。假設我們要模仿一個簡單的分散式 NoSQL 資料庫系統,可以分成以下幾個組件:
首先,確認你有一個 Kubernetes 集群運行。可以使用 Minikube 或 GKE 等 Kubernetes 平台。為了建立這個系統,我們會使用 StatefulSets 來管理資料庫的狀態,以及 PersistentVolume (PV) 和 PersistentVolumeClaim (PVC) 來持久化資料。
StatefulSet 用來管理有狀態的應用,比如資料庫節點。這裡我們使用 etcd 作為示例,它是一個分散式資料庫,模仿 Google 的 GFS 系統。
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: etcd-cluster
spec:
serviceName: "etcd"
replicas: 3
selector:
matchLabels:
app: etcd
template:
metadata:
labels:
app: etcd
spec:
containers:
- name: etcd
image: quay.io/coreos/etcd:v3.4.13
ports:
- containerPort: 2379
name: client
- containerPort: 2380
name: peer
volumeMounts:
- name: etcd-data
mountPath: /var/lib/etcd
env:
- name: ETCD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: ETCD_INITIAL_ADVERTISE_PEER_URLS
value: http://$(ETCD_NAME).etcd:2380
- name: ETCD_ADVERTISE_CLIENT_URLS
value: http://$(ETCD_NAME).etcd:2379
- name: ETCD_INITIAL_CLUSTER
value: etcd-0=http://etcd-0.etcd:2380,etcd-1=http://etcd-1.etcd:2380,etcd-2=http://etcd-2.etcd:2380
- name: ETCD_INITIAL_CLUSTER_TOKEN
value: etcd-cluster-1
- name: ETCD_INITIAL_CLUSTER_STATE
value: "new"
volumeClaimTemplates:
- metadata:
name: etcd-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
這個 YAML 檔案定義了一個 3 節點的 etcd 叢集,每個節點有一個 PersistentVolumeClaim 來保存資料。該集群會使用 Kubernetes 的 DNS 來讓節點間互相發現彼此。
還需要定義一個 Service,用來公開 etcd 叢集內部的對等通訊,以及客戶端的資料存取:
apiVersion: v1
kind: Service
metadata:
name: etcd
spec:
clusterIP: None
ports:
- port: 2379
name: client
- port: 2380
name: peer
selector:
app: etcd
這個 Service 會為 etcd 提供穩定的網路端點。
每個 etcd 節點需要一個 PersistentVolume 來確保資料不會因為 Pod 重啟而丟失。定義一個動態配置 PersistentVolume 的 StorageClass 和 PersistentVolumeClaim:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/aws-ebs # 可以根據你的平台選擇不同的 provisioner
parameters:
type: gp2
使用 kubectl
部署上面的資源:
kubectl apply -f etcd-statefulset.yaml
kubectl apply -f etcd-service.yaml
kubectl apply -f storageclass.yaml
這樣你會得到一個運行在 Kubernetes 上的分散式 etcd 叢集。你可以把這個系統作為分散式資料存取的基礎,模仿 Google 的 GFS 系統進行讀寫操作。
可以使用 etcdctl
工具來測試叢集的資料寫入和讀取:
etcdctl --endpoints=http://<etcd-cluster-endpoint>:2379 put foo "Hello, World!"
etcdctl --endpoints=http://<etcd-cluster-endpoint>:2379 get foo
StatefulSet
解釋StatefulSet
是 Kubernetes 中專門用來管理有狀態應用的資源。它確保每個 Pod 都有一個固定的身份(名稱),並且持久化資料即使 Pod 重啟或重新安排,資料依然能夠保留。這裡的 StatefulSet
用來創建和管理一個 3 節點的 etcd
叢集。
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: etcd-cluster
apiVersion
:指定此資源使用的 Kubernetes API 版本,apps/v1
是用於管理應用的版本。kind
:表示這是一個 StatefulSet
,用於管理有狀態的應用。metadata
:包含此資源的名稱,即 etcd-cluster
,這個名稱會用來標識這個 StatefulSet
。spec
):spec:
serviceName: "etcd"
replicas: 3
selector:
matchLabels:
app: etcd
serviceName
:這裡定義了這個 StatefulSet
所屬的服務名稱。這個服務會讓 Pod 之間可以互相通訊。replicas
:表示應該有 3 個 etcd
節點,也就是 3 個 Pod。selector
:用來選擇標籤為 app=etcd
的 Pod,這些 Pod 屬於這個 StatefulSet。template
):template:
metadata:
labels:
app: etcd
spec:
containers:
- name: etcd
image: quay.io/coreos/etcd:v3.4.13
ports:
- containerPort: 2379
name: client
- containerPort: 2380
name: peer
volumeMounts:
- name: etcd-data
mountPath: /var/lib/etcd
template.metadata.labels
:這裡為每個 Pod
設置標籤 app=etcd
,這樣 Kubernetes 知道哪些 Pod 屬於這個 StatefulSet。containers
:定義了運行在 Pod 中的容器。這裡有一個名為 etcd
的容器,使用 etcd
版本 v3.4.13
的 Docker 映像。ports
:兩個端口用於不同用途:
volumeMounts
:將命名為 etcd-data
的持久化卷掛載到容器的 /var/lib/etcd
目錄,這是 etcd
存儲數據的地方。env
):env:
- name: ETCD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: ETCD_INITIAL_ADVERTISE_PEER_URLS
value: http://$(ETCD_NAME).etcd:2380
- name: ETCD_ADVERTISE_CLIENT_URLS
value: http://$(ETCD_NAME).etcd:2379
- name: ETCD_INITIAL_CLUSTER
value: etcd-0=http://etcd-0.etcd:2380,etcd-1=http://etcd-1.etcd:2380,etcd-2=http://etcd-2.etcd:2380
- name: ETCD_INITIAL_CLUSTER_TOKEN
value: etcd-cluster-1
- name: ETCD_INITIAL_CLUSTER_STATE
value: "new"
這些環境變量告訴每個 etcd
節點如何進行初始化和彼此之間的連接。
ETCD_NAME
:動態生成每個 Pod
的名稱,來自於 Kubernetes 的 metadata.name
。ETCD_INITIAL_ADVERTISE_PEER_URLS
和 ETCD_ADVERTISE_CLIENT_URLS
:分別指定節點間互相廣告的對等 URL 和客戶端連接 URL。ETCD_INITIAL_CLUSTER
:列出叢集中的所有節點,用來讓它們進行節點間的同步。ETCD_INITIAL_CLUSTER_STATE
:指定叢集的初始狀態,new
表示這是一個新建立的叢集。volumeClaimTemplates
):volumeClaimTemplates:
- metadata:
name: etcd-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
volumeClaimTemplates
:這裡定義了每個 etcd
節點所使用的持久化存儲。每個 Pod 都會獲得 1GB 的存儲,來保存其資料。accessModes
:ReadWriteOnce
表示該卷只能被一個節點同時掛載並進行讀寫。Service
解釋這個服務的定義用來允許外部客戶端訪問 etcd
叢集,並且確保叢集內部節點間的對等通訊。
apiVersion: v1
kind: Service
metadata:
name: etcd
spec:
clusterIP: None
ports:
- port: 2379
name: client
- port: 2380
name: peer
selector:
app: etcd
kind
:定義這個資源是 Service
。clusterIP: None
:指定這個服務是 "Headless Service",不分配 ClusterIP,只用來讓 Pod 之間進行發現。ports
:定義服務公開的端口:
selector
:選擇 app=etcd
標籤的 Pod,也就是與該 StatefulSet
關聯的 Pod。PersistentVolume
和 PersistentVolumeClaim
解釋這部分負責為每個 etcd
節點提供持久化存儲,確保即使 Pod 重啟,數據依然存在。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
StorageClass
:定義一個存儲類別,這裡用 kubernetes.io/aws-ebs
作為 provisioner(如果你在 AWS 平台上運行 Kubernetes)。這個類別會自動動態地創建 PersistentVolume
,並使用 gp2
類型的 AWS EBS 卷來提供存儲。這段程式碼定義了一個 3 節點的 etcd
叢集,每個節點都有自己的持久化存儲卷,並且使用 StatefulSet
來確保每個節點都有穩定的網路身份和持久化的數據存儲。Service
提供了叢集內節點間的通訊,以及外部客戶端的存取點。